﻿/*-------------------------------------------------------------------------
* 命名空间: WaferSelectV3.PlcCommunication/BeckhoffPlcClient
* 类       名: BeckhoffPlcClient
* 功      能:  TD
* 时      间:  2024-05-14 17:40:46
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TwinCAT.Ads;
using WaferSelectV3.Common;
using WaferSelectV3.Extensions;
using WaferSelectV3.Models;

namespace WaferSelectV3.PlcCommunication
{
    public class BeckhoffPlcClient
    {
        private AdsClient NetClient = null!;
        private static BeckhoffPlcClient? _instance;
        /// <summary>
        /// 料盒结果写入的数组的位置索引
        /// </summary>
        public int BoxResWriteIndex { get; set; }
        private static readonly object _lock = new object();

        private BeckhoffPlcClient()
        {
            NetClient = new AdsClient();
            BoxResWriteIndex = 1;
        }

        public static BeckhoffPlcClient Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new BeckhoffPlcClient();
                        }
                    }
                }
                return _instance;
            }
        }

        internal DataResult WriteBoxNumber(int waferId, int boxNumber)
        {

            DataResult result = new DataResult();

            try
            {
                string plcPos = $"Global_ID.PC_Data";
                int indexStart = BoxResWriteIndex;
                int[] writeVal = new int[] { waferId, boxNumber };
                if (BoxResWriteIndex >= 9)
                {
                    BoxResWriteIndex = 1;
                }
                else
                {
                    BoxResWriteIndex += 2;
                }
                return WriteDInt32bitArray(plcPos, writeVal, indexStart);

            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
                return result;
            }
        }

        /// <summary>
        /// 连接Plc,连接成功之后,重置电阻率的值
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public DataResult ConnectPlc(string ip, int port)
        {
            DataResult result = new DataResult();
            try
            {
                NetClient!.Connect(ip, port);
                if (!NetClient.IsConnected)
                {
                    result.Message = $"Plc连接失败,连接Ip: {ip}, Port: {port},请检查配置和网线!";
                }
                else
                {
                    result.State = true;
                    // 1. 连接成功之后,重置电阻率的值
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 获取电阻率测试的流水号 Global_ID.IDSend2  :DINT
        /// </summary>
        /// <returns></returns>
        public DataResult<int> GetWaferIdForResistivity()
        {
            string plcPos = "Global_ID.IDSend2";
            DataResult<int> result = new DataResult<int>();
            try
            {
                return ReadDInt32Bit(plcPos);
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }
        /// <summary>
        /// 重置电阻率流水号为0
        /// </summary>
        /// <returns></returns>
        public DataResult ResetResistivityWaferId(int resetVal = 0)
        {
            string plcPos = "Global_ID.IDSend2";
            DataResult result = new DataResult();
            try
            {
                return WriteDInt32Bit(plcPos, resetVal);
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }



        /// <summary>
        /// PLC数据类型bool C# bool
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<bool> ReadBool(string varName)
        {
            DataResult<bool> result = new DataResult<bool>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (bool)NetClient.ReadAny(handle, typeof(bool));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }


        /// <summary>
        /// PLC数据类型Byte(8bit) C# byte
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<byte> ReadByte(string varName)
        {
            DataResult<byte> result = new DataResult<byte>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (byte)NetClient.ReadAny(handle, typeof(byte));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// PLC数据类型SINT(8-bit)  C# sbyte
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<sbyte> ReadSInt8Bit(string varName)
        {
            DataResult<sbyte> result = new DataResult<sbyte>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (sbyte)NetClient.ReadAny(handle, typeof(sbyte));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }


        /// <summary>
        /// PLC数据类型INT(16-bit)  C# Short
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<short> ReadInt16Bit(string varName)
        {
            DataResult<short> result = new DataResult<short>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (short)NetClient.ReadAny(handle, typeof(short));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }


        /// <summary>
        /// PLC数据类型DINT  C# int
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<int> ReadDInt32Bit(string varName)
        {
            DataResult<int> result = new DataResult<int>();
            uint handle = 0u;
            try
            {
                handle = NetClient.CreateVariableHandle(varName);
                var value = (int)NetClient.ReadAny(handle, typeof(int));
                result.Data = value;
                result.State = true;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            finally
            {
                if (handle != 0u)
                {
                    NetClient.DeleteVariableHandle(handle);
                }
            }
            return result;
        }

        /// <summary>
        /// PLC数据类型DINT  C# int
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult WriteDInt32Bit(string varName, int writeVal)
        {
            DataResult result = new DataResult();
            uint handle = 0u;
            try
            {
                handle = NetClient.CreateVariableHandle(varName);
                NetClient.WriteAny(handle, writeVal);
                result.State = true;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            finally
            {
                if (handle != 0u)
                {
                    NetClient.DeleteVariableHandle(handle);
                }
            }
            return result;
        }


        /// <summary>
        /// PLC数据类型LINT  C# long
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<long> ReadLInt64Bit(string varName)
        {
            DataResult<long> result = new DataResult<long>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (long)NetClient.ReadAny(handle, typeof(long));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }


        /// <summary>
        /// PLC数据类型REAL  C# float
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<float> ReadReal32bit(string varName)
        {
            DataResult<float> result = new DataResult<float>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (float)NetClient.ReadAny(handle, typeof(float));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// PLC读取数据类型LReal(64bit) C# double
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public DataResult<double> ReadLReal64bit(string varName)
        {
            DataResult<double> result = new DataResult<double>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                var value = (double)NetClient.ReadAny(handle, typeof(double));
                result.Data = value;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }


        /// <summary>
        /// 读取DINT类型数组的值
        /// </summary>
        /// <returns></returns>
        public DataResult<int[]> ReadDInt32bitArray(string varName, int arrayLength)
        {
            DataResult<int[]> result = new DataResult<int[]>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                int[] intArray = (int[])NetClient.ReadAny(handle, typeof(int[]), new int[] { arrayLength });
                result.Data = intArray;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }


        /// <summary>
        /// 写入DINT类型数组的值
        /// </summary>
        /// <returns></returns>
        public DataResult WriteDInt32bitArray(string varName, int[] writeData, int indexStart)
        {
            DataResult result = new DataResult();
            uint handle = 0u;
            try
            {
                string plcPos = $"{varName}[{indexStart + 1}]";
                handle = NetClient.CreateVariableHandle(plcPos);
                NetClient.WriteAny(handle, writeData[1]);
                plcPos = $"{varName}[{indexStart}]";
                handle = NetClient.CreateVariableHandle(plcPos);
                NetClient.WriteAny(handle, writeData[0]);
                result.State = true;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            finally
            {
                NetClient.DeleteVariableHandle(handle);
            }
            return result;
        }


        /// <summary>
        /// 读取INT类型数组的值 C# 数据类型short
        /// </summary>
        /// <returns></returns>
        public DataResult<short[]> ReadInt16bitArray(string varName, int arrayLength)
        {
            DataResult<short[]> result = new DataResult<short[]>();
            try
            {
                var handle = NetClient.CreateVariableHandle(varName);
                short[] intArray = (short[])NetClient.ReadAny(handle, typeof(short[]), new int[] { arrayLength });
                result.Data = intArray;
            }
            catch (Exception ex)
            {
                result.Message = ex.Message;
            }
            return result;
        }
    }
}
